package com.SpringCloud.flowable.controller;


import com.SpringCloud.flowable.vo.LeaveTaskVO;
import com.SpringCloud.flowable.vo.Result;
import com.SpringCloud.flowable.vo.TaskVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.engine.*;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.image.ProcessDiagramGenerator;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/leave")
@Slf4j
@Tag(name = "请假流程")
public class LeaveController {
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private ProcessEngine processEngine;

    @PostMapping(value = "/deploy")
    @Transactional(rollbackFor = Exception.class)
    @Operation(summary = "部署请假流程")
    public Result deployModel() {
        final String filePath = System.getProperty("user.dir") + "/flowable-service/src/main/processes/请假流程.bpmn20.xml";
        try (FileInputStream fis = new FileInputStream(filePath)) {
            Deployment deploy = repositoryService.createDeployment()
                    .addInputStream("请假流程.bpmn20.xml", fis)
                    .name("请假流程")
                    .deploy();

            System.out.println("部署ID：" + deploy.getId());
            return new Result(true, "部署成功");
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(false, "部署失败：" + e.getMessage());
        }
    }
//    public Result deployModel(@RequestParam("file") MultipartFile file,
//                              @RequestParam("name") String name) {
//        try (InputStream inputStream = file.getInputStream()) {
//            Deployment deployment = repositoryService.createDeployment()
//                    .addInputStream(file.getOriginalFilename(), inputStream)
//                    .name(name)
//                    .deploy();
//
//            System.out.println("部署ID：" + deployment.getId());
//            return new Result(true, "部署成功");
//        } catch (Exception e) {
//            e.printStackTrace();
//            return new Result(false, "部署失败：" + e.getMessage());
//        }
//    }
    @PostMapping( "add/{day}/{studentUser}")
    @Operation(summary = "学生提交请假申请")
    public Result sub(@PathVariable("day") Integer day , @PathVariable("studentUser") String studentUser) {
        // 1. 保存业务数据
//        StudentLeave leave = new StudentLeave();
//        leave.setId(12345678L);
//        leave.setStudentName(studentUser);
//        leave.setDays(day);
//        leave.setStatus("SUBMITTED");
//        studentLeaveService.save(leave);
        // 2. 启动流程  // 学生提交请假申请
        Map<String, Object> vars = new HashMap<>();
        //vars.put("businessId", leave.getId()); // 关键关联变量
        vars.put("day", day);
        vars.put("studentName", studentUser);

        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(
                "stuLeave",
                //String.valueOf(leave.getId()), // 业务ID作为BusinessKey
                vars
        );

        log.info("流程实例ID：" + processInstance.getId());
        //完成申请任务
        Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
        taskService.complete(task.getId());
        //此处id为流程id
        return new Result(true,"提交成功.流程Id为：" + processInstance.getId()) ;
    }

    @GetMapping("teacherList")
    @Operation(summary = "辅导员查看请假申请")
    public Result teacherList() {
//        //此处.taskCandidateGroup("a")的值“a”即是画流程图时辅导员审批节点"分配用户-候选组"中填写的值
//        List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("a").list();
//        List<TaskVO> taskVOList = tasks.stream().map(task -> {
//            Map<String, Object> variables = taskService.getVariables(task.getId());
//            return new TaskVO(task.getId(), variables.get("day").toString(), variables.get("studentName").toString());
//        }).collect(Collectors.toList());
//        log.info("任务列表：" + tasks);
//        if (tasks == null || tasks.size() == 0) {
//            return new Result(false,"没有任务");
//        }
//        return new Result(true,"获取成功",taskVOList);
        List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("a").list();

        if (tasks == null || tasks.isEmpty()) {
            return new Result(false, "没有待办任务");
        }

        List<LeaveTaskVO> taskVOList = new ArrayList<>();
        for (Task task : tasks) {
            try {
                Object businessIdObj = taskService.getVariable(task.getId(), "businessId");
                if (businessIdObj == null) {
                    log.warn("任务 {} 缺少businessId变量", task.getId());
                    continue;
                }

                Long businessId = Long.parseLong(businessIdObj.toString());
               // Optional<StudentLeave> leaveOpt = Optional.ofNullable(studentLeaveService.getById(businessId));

//                if (!leaveOpt.isPresent()) {
//                    log.warn("业务数据不存在，businessId: {}", businessId);
//                    continue;
//                }
//
//                StudentLeave leave = leaveOpt.get();
                Map<String, Object> variables = taskService.getVariables(task.getId());

                taskVOList.add(new LeaveTaskVO(
                        task.getId(),
                        task.getName(),  // 任务名称
                        task.getCreateTime(),  // 任务创建时间
                        businessId,
                        "",
1,
"1",
//                        leave.getStudentName(),
//                        leave.getDays(),
//                        leave.getStatus(),
                        variables
                ));
            } catch (Exception e) {
                log.error("处理任务 {} 时出错", task.getId(), e);
            }
        }

        if (taskVOList.isEmpty()) {
            return new Result(false, "没有可处理的待办任务");
        }

        return new Result(true, "获取成功", taskVOList);
    }

    /**
     * 辅导员批准
     *
     * @param taskId 任务ID，非流程id
     */
    @GetMapping("teacherApply/{taskId}")
    @Operation(summary = "辅导员批准请假申请")
    public Result teacherApply(@PathVariable("taskId") String taskId) {
        List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("a").list();
        Task task = taskService.createTaskQuery().taskCandidateGroup("a").taskId(taskId).singleResult();
        if (task == null) {
            return new Result(false, "没有任务");
        }
        //通过审核
        HashMap<String, Object> map = new HashMap<>();
        map.put("outcome", "通过");
//        for (Task task : tasks) {
//            taskService.complete(task.getId(), map);
//        }
        taskService.complete(task.getId(), map);
        return new Result(true,"审批成功");
    }

    /**
     * 辅导员拒绝
     * @param taskId 任务ID，非流程id
     */
    @GetMapping( "teacherReject/{taskId}")
    @Operation(summary = "辅导员拒绝请假申请")
    public Result teacherReject(@PathVariable("taskId") String taskId) {
        Task task1 = taskService.createTaskQuery().taskCandidateGroup("a").taskId(taskId).singleResult();
        //Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task1 == null) {
            return new Result(false, "没有任务");
        }
        //通过审核
        HashMap<String, Object> map = new HashMap<>();
        map.put("outcome", "驳回");
        taskService.complete(task1.getId(), map);
        return new Result(true,"驳回成功");
    }
    /**
     * 院长获取审批管理列表
     */
    @GetMapping("deanList")
    @Operation(summary = "院长获取审批管理列表")
    public Result deanList() {
        //此处.taskCandidateGroup("b")的值“b”即是画流程图时辅导员审批节点"分配用户-候选组"中填写的值
        List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("b").list();
        List<TaskVO> taskVOList = tasks.stream().map(task -> {
            Map<String, Object> variables = taskService.getVariables(task.getId());
            return new TaskVO(task.getId(), variables.get("day").toString(), variables.get("studentName").toString());
        }).collect(Collectors.toList());
        if (tasks == null || tasks.size() == 0) {
            return new Result(false,"没有任务");
        }
        return new Result(true,"获取成功",taskVOList);
    }

    /**
     * 院长批准
     * @param taskId 任务ID，非流程id
     * @return
     */
    @GetMapping("deanApply/{taskId}")
    @Operation(summary = "院长批准请假申请")
    public Result apply(@PathVariable("taskId") String taskId) {
        List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("b").list();
        //Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (tasks == null) {
            return new Result(false, "没有任务");
        }
        //通过审核
        HashMap<String, Object> map = new HashMap<>();
        map.put("outcome", "通过");
        for (Task task : tasks) {
            taskService.complete(task.getId(), map);
        }
        return new Result(true,"审批成功");
    }

    /**
     * 院长拒绝
     * @param taskId 任务ID，非流程id
     * @return
     */
    @GetMapping("deanReject/{taskId}")
    @Operation(summary = "院长拒绝请假申请")
    public Result deanReject(@PathVariable("taskId") String taskId) {
//        List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("b").list();
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task == null) {
            return new Result(false, "没有任务");
        }
        //通过审核
        HashMap<String, Object> map = new HashMap<>();
        map.put("outcome", "驳回");
//        for (Task task : tasks) {
//            taskService.complete(task.getId(), map);
//        }
        taskService.complete(task.getId(), map);
        return new Result(true,"审批成功");
    }

    /**
     * 再次申请
     * @param piId 流程id
     * @param day
     * @return
     */
    @GetMapping("subAgain/{piId}/{day}")
    @Operation(summary = "再次申请")
    public Result subAgain(@PathVariable("piId") String piId, @PathVariable("day") Integer day){
        Task task = taskService.createTaskQuery().processInstanceId(piId).singleResult();
        if(Objects.isNull(task)){
            return new Result(false, "没有任务");
        }
        Map<String, Object> map = new HashMap<>();
        map.put("day", day);
        taskService.complete(task.getId(), map);
        return new Result(true,"申请成功");
    }

    /**
     * 生成流程图
     *
     * @param taskId 流程ID
     */
    @GetMapping( "processDiagram/{taskId}")
    @Operation(summary = "生成流程图")
    public void genProcessDiagram(HttpServletResponse httpServletResponse, @PathVariable("taskId") String taskId) throws Exception {
        ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(taskId).singleResult();

        //流程走完的不显示图
        if (pi == null) {
            return;
        }
        Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).singleResult();
        //使用流程实例ID，查询正在执行的执行对象表，返回流程实例对象
        String InstanceId = task.getProcessInstanceId();
        List<Execution> executions = runtimeService
                .createExecutionQuery()
                .processInstanceId(InstanceId)
                .list();

        //得到正在执行的Activity的Id
        List<String> activityIds = new ArrayList<>();
        List<String> flows = new ArrayList<>();
        for (Execution exe : executions) {
            List<String> ids = runtimeService.getActiveActivityIds(exe.getId());
            activityIds.addAll(ids);
        }

        //获取流程图
        BpmnModel bpmnModel = repositoryService.getBpmnModel(pi.getProcessDefinitionId());
        ProcessEngineConfiguration engconf = processEngine.getProcessEngineConfiguration();
        ProcessDiagramGenerator diagramGenerator = engconf.getProcessDiagramGenerator();
        InputStream in = diagramGenerator.generateDiagram(bpmnModel,
                "png", activityIds, flows, engconf.getActivityFontName(),
                engconf.getLabelFontName(), engconf.getAnnotationFontName(), engconf.getClassLoader(),
                1.0 ,true);
        OutputStream out = null;
        byte[] buf = new byte[1024];
        int legth = 0;
        try {
            //此处设置resp的header诸多文章都没写，但是我不写出不来流程图，诸位可去掉试试
            httpServletResponse.setHeader("Content-Type",
                    "image/png;charset=utf-8");
            out = httpServletResponse.getOutputStream();
            while ((legth = in.read(buf)) != -1) {
                out.write(buf, 0, legth);
            }
        } finally {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
        }
    }
}
